using System;

using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Server
{
	[Serializable]
	class AccountField
	{
		internal string password;
		internal bool isLoggedIn;
		internal bool visible;
		internal ArrayList contacts;

		public AccountField(string password, bool isLoggedIn)
		{
			this.password = password;
			this.isLoggedIn = isLoggedIn;
			contacts = new ArrayList();
		}
	}

	[Serializable]
	class Database
	{
		private Hashtable database;
		internal ArrayList offlineMessages;
		internal ArrayList tasks;

		public Database()
		{
			database = new Hashtable();
			offlineMessages=new ArrayList();
			tasks = new ArrayList();
			Load();
		}

		internal AccountField AccountField
		{
			get
			{
				throw new System.NotImplementedException();
			}
			set
			{
			}
		}

		//Methods
		internal bool Add(string username,string password)
		{
			if(database.Contains(username))
				return false;
			database.Add(username,new AccountField(password,false));
			return Save();
		}
		internal bool ChangePassword(string username,string curPassword,string newPassword)
		{
			if(database.Contains(username))
			{
				if(((AccountField)database[username]).password==curPassword)
				{
					((AccountField)database[username]).password=newPassword;
					Save();
					return true;
				}
				else
				{
					return false;
				}
			}
			else
			{
				return false;
			}
		}
		internal bool SignIn(string username,string password,bool visible)
		{
			if(database.Contains(username))
			{
				if(((AccountField)database[username]).password==password)
				{
					((AccountField)database[username]).isLoggedIn=true;
					((AccountField)database[username]).visible=visible;
					Console.WriteLine(username+" has signed in");
					return true;
				}
				else
				{
					return false;
				}
			}
			return false;
		}
		internal bool SignOut(string username)
		{
			if(database.Contains(username))
			{
				((AccountField)database[username]).isLoggedIn=false;
				((AccountField)database[username]).visible=false;
				Console.WriteLine(username+" has signed out");
				return true;
			}
			return false;
		}
		internal bool ContactExists(string username)
		{
			return (database.Contains(username));
		}
		internal bool IsLoggedIn(string username)
		{
			if(database.Contains(username))
			{
				return ((AccountField)database[username]).isLoggedIn;
			}
			else
			{
				return false;
			}
		}
		internal bool IsVisible(string username)
		{
			if(database.Contains(username))
			{
				return ((AccountField)database[username]).visible;
			}
			else
			{
				return false;
			}
		}
		internal bool AddContact(string username,string contact)
		{
			if(database.Contains(username))
			{
				if(((AccountField)database[username]).contacts.Contains(contact))
					return false;
				if(database.Contains(contact))
				{
					((AccountField)database[username]).contacts.Add(contact);
					return Save();
				}
			}
			return false;
		}
		internal bool RemoveContact(string username,string contact)
		{
			if(database.Contains(username))
			{
				if(((AccountField)database[username]).contacts.Contains(contact))
				{
					((AccountField)database[username]).contacts.Remove(contact);
					return Save();
				}
			}
			return false;
		}
		internal ArrayList GetContacts(string username)
		{
			if(database.Contains(username))
			{
				return ((AccountField)database[username]).contacts;
			}
			return null;
		}

		internal bool Load()
		{
			try
			{
				FileStream fileStream = new FileStream("AccDB.dat",FileMode.Open);
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				Database temp = (Database)binaryFormatter.Deserialize(fileStream);
				this.database = temp.database;
				this.offlineMessages = temp.offlineMessages;
				this.tasks = temp.tasks;
				fileStream.Close();
				return true;
			}
			catch
			{
				database = new Hashtable();
				offlineMessages=new ArrayList();
				return false;
			}
		}
		internal bool Save()
		{
			try
			{
				FileStream fileStream =
					new FileStream("AccDB.dat",FileMode.Create);
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				binaryFormatter.Serialize(fileStream,this);	
				fileStream.Close();
				return true;
			}
			catch(Exception e)
			{
				Console.WriteLine(e.ToString());
				return false;
			}
		}
	}
}